package tencent

import (
	"context"
	"fmt"
	"github.com/ecodeclub/ekit"
	"github.com/ecodeclub/ekit/slice"
	sms "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms/v20210111"
	"go.uber.org/zap"
)

// Service 短信服务-腾讯云实现
type Service struct {
	client *sms.Client
	appId  *string
	// 这里用指针是因为腾讯云API要求的，这是种不好的设计，需要判断是否为nil
	signName *string
}

func NewService(client *sms.Client, appId, signName string) *Service {
	return &Service{
		client:   client,
		appId:    &appId,
		signName: &signName,
	}
}

// Send 腾讯云实现发送短信
func (s *Service) Send(ctx context.Context, templateId string,
	args []string, number ...string) error {
	// 实例化一个请求对象
	request := sms.NewSendSmsRequest()
	request.SetContext(ctx)
	// 短信应用ID
	request.SmsSdkAppId = s.appId
	// 短信签名内容
	request.SignName = s.signName
	// 模板 ID
	request.TemplateId = ekit.ToPtr[string](templateId)
	// 模板 参数
	//request.TemplateParamSet = common.StringPtrs(args)
	request.TemplateParamSet = s.toPtrSlice(args)
	// 下发手机号码 格式：+[国家或地区码][手机号]
	//request.PhoneNumberSet = common.StringPtrs(number)
	request.PhoneNumberSet = s.toPtrSlice(number)

	// 发送信息
	response, err := s.client.SendSms(request)
	zap.L().Debug("调用腾讯云短信服务",
		zap.Any("req", request),
		zap.Any("resp", response),
	)
	if err != nil {
		fmt.Printf("An API error has returned: %s", err)
		return err
	}
	// 有几个电话号码，就有几个 SendStatus
	for _, statusPtr := range response.Response.SendStatusSet {
		if statusPtr == nil {
			// 基本上不可能进入这里
			continue
		}
		status := *statusPtr
		// 如果发送成功 Code == "Ok"，否则为失败
		if status.Code == nil || *(status.Code) != "Ok" {
			// 正常 status.Code 是不会为nil的
			return fmt.Errorf("发送短信失败, code:%s, msg:%s", *status.Code, *status.Message)
		}
	}
	return nil
}

// []string -> []*string
func (s *Service) toPtrSlice(data []string) []*string {
	return slice.Map[string, *string](data,
		func(idx int, src string) *string {
			return &src
		})
}
